home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / crit.arc / CRIT.ASM next >
Assembly Source File  |  1986-12-03  |  5KB  |  168 lines

  1. ;
  2. ; testcrit.asm - implements a 'setjmp' style critical error handler
  3. ; for Microsoft C.  Implementation with other compilers should be trivial.
  4. ; define LARGE_CODE to compile for large code models
  5. ;
  6. ifdef MMODEL
  7. LARGECODE EQU 1
  8. endif
  9. ifdef LMODEL
  10. LARGECODE EQU 1
  11. endif
  12. ifdef HMODEL
  13. LARGECODE    EQU 1
  14. endif
  15.  
  16. _TEXT    segment public 'CODE'
  17.  
  18. _DATA    segment public 'DATA'
  19. _DATA    ends
  20.  
  21. assume cs:_TEXT,ds:_DATA
  22.  
  23. old_handler    label dword
  24. old_off    dw ?
  25. old_seg    dw ?
  26.  
  27. critical    equ 24H
  28.  
  29. savess    dw    ?
  30. savesp    dw    ?
  31. savebp    dw    ?
  32. savesi    dw    ?
  33. savedi    dw    ?
  34. returnaddress    dw    ?
  35. ifdef LARGE_CODE
  36. returnsegment    dw    ?
  37. endif
  38. datasegment    dw    ?
  39. extrasegment    dw    ?
  40. counter    dw    0
  41.  
  42. ; crit_handler is where the critical error vector is pointed.
  43. ; it follows the suggestions found in the DOS technical reference handler,
  44. ; i.e. it calls the old handler, and decides what to do on the basis of the
  45. ; value returned in AL
  46.     public crit_handler
  47. crit_handler proc near
  48.     pushf                                ; push flags to simulate s/w interrupt
  49.     call    dword ptr cs:old_handler    ; call the old handler
  50.     cmp        al,2                        ; is this an abort?
  51.     je do_abort                            ; if it is, handle abort
  52.     iret                                ; if not, just iret
  53. do_abort:
  54.     ; otherwise, restore environment
  55.     cli                                    ; disable interrupts
  56.     ; restore all important registers to the values they had upon entry
  57.     ; into setup_crit, set AX to -1 and return
  58.     mov    ss,cs:savess
  59.     mov    sp,cs:savesp
  60.     mov    bp,cs:savebp
  61.     mov    si,cs:savesi
  62.     mov    di,cs:savedi
  63.     mov    ds,cs:datasegment
  64.     mov    es,cs:extrasegment
  65.     mov    bx,cs:returnaddress                ; pick up return address
  66.     mov    ax,-1                            ; return -1
  67.     sti                                    ; enable interrupts
  68. ifdef LARGE_CODE
  69.     jmp    dword ptr cs:returnaddress
  70. else
  71.     jmp    bx
  72. endif
  73. crit_handler    endp
  74.  
  75. ;
  76. ; setup_crit - sets up the critical error handler.
  77. ; When this is called initially it will return 0.
  78. ; If a critical error occurs, and the user responds with 'abort'
  79. ; to the abort, retry, ignore message, then it will return -1.
  80. ; This is very similar to the setjmp/longjmp non-local goto interface in
  81. ; the standard C library
  82. ;
  83.     public _setup_crit
  84. ifdef LARGE_CODE
  85. _setup_crit    proc    far
  86. else
  87. _setup_crit    proc    near
  88. endif
  89.     ; the counter variable is an interlock - if you call setup_crit
  90.     ; if another call to setup_crit is already pending, then restore_crit will
  91.     ; be called in order to restore the old vector before installing the new
  92.     ; one.
  93.     cmp    cs:counter,0                    ; have we been here before?
  94.     je continue                            ; if not, keep going
  95. ifdef LARGE_CODE
  96.     call far ptr _restore_crit
  97. else
  98.     call _restore_crit                    ; otherwise restore old handler 1st
  99. endif
  100. continue:
  101.     inc    cs:counter                        ; bump the counter
  102.     push    es                            ; save registers munged
  103.     push    ds                            ;
  104.     push    si                            ;
  105.     xor    ax,ax                            ; address interrupt vectors
  106.     mov    ds,ax
  107.     mov    bx,critical*4                    ; offset of critical error handler
  108.     les si,[bx]                            ; load into es:si
  109.     mov    cs:old_off,si                    ; save offset
  110.     mov    cs:old_seg,es                    ; save segment
  111.     mov    word ptr [bx],offset crit_handler    ; install new handler
  112.     mov    2[bx],cs                        ; handler segment
  113.     pop    si                                ; restore munged variables
  114.     pop    ds                                ;
  115.     pop    es                                ;
  116.     ; save the relevant calling environment, which consists of
  117.     ; ss,sp,bp (stack environment) si,di (possible register vars)
  118.     ; and ds,es (data segments)
  119.     mov    cs:savess,ss
  120.     mov    cs:savesp,sp
  121.     mov    cs:savebp,bp
  122.     mov    cs:savesi,si
  123.     mov    cs:savedi,di
  124.     mov    cs:datasegment,ds
  125.     mov    cs:extrasegment,es
  126.     xor    ax,ax                            ; return 0
  127.     pop    bx                                ; get return address
  128.     mov    cs:returnaddress,bx                ; save it
  129. ifdef LARGE_CODE
  130.     pop    bx                                ; get return segment
  131.     mov    cs:returnsegment,bx
  132.     jmp dword ptr cs:returnaddress
  133. else
  134.     jmp    bx                                ; go to return address
  135. endif
  136. _setup_crit    endp
  137.  
  138.     public _restore_crit
  139. ifdef LARGE_CODE
  140. _restore_crit    proc    far
  141. else
  142. _restore_crit    proc    near
  143. endif
  144.     ; check the counter to make sure setup_crit has already been called
  145.     cmp    cs:counter,1                    ; has it been called?
  146.     je restore                            ; yes, restore environment
  147.     ret                                    ; no, do nothing
  148. restore:
  149.     dec    cs:counter                        ; make counter 0
  150.     push    es                            ; save registers munged
  151.     push    ds                            ;
  152.     push    si                            ;
  153.     xor    ax,ax                            ; address interrupt vectors
  154.     mov    ds,ax                            ;
  155.     les    si,cs:old_handler                ; pick up old handler into es:si
  156.     mov    bx,critical*4                    ; address critical vector
  157.     mov    [bx],si                            ; poke old handler back in
  158.     mov    2[bx],es                        ;
  159.     pop    si                                ; restore munged registers
  160.     pop    ds                                ;
  161.     pop    es                                ;
  162.     ret                                    ; go away
  163. _restore_crit    endp
  164.  
  165. _TEXT    ends
  166.     end
  167.     
  168.